#!/bin/bash

# 作者：无涯有涯
# 功能：备份CloudNativePG管理的PostgreSQL集群数据库
# 用法：curl -sSL https://gitee.com/veryx/galaxy-tools/raw/master/5-cnpg/pg_backup.sh | bash -s -- --db <dbname> --out <backup_dir>

set -eo pipefail
set -E

[[ $# -eq 0 ]] && echo "用法: $(basename $0) --db <dbname> --out <backup_dir>" && exit 0
DBNAME=""
BACKUP_DIR=""
while [[ $# -gt 0 ]]; do
    case "$1" in
        --db) DBNAME="$2"; shift 2 ;;
        --out) BACKUP_DIR="$2"; shift 2 ;;
        --help) echo "用法: $(basename $0) --db <dbname> --out <backup_dir>" && exit 0 ;;
        *)  echo "错误参数: $1";exit 1 ;;
    esac
done

if [[ -z "$BACKUP_DIR" || -z "$DBNAME" ]]; then
    echo "错误：必须提供数据库名和备份目录！"
    exit 1
fi

if [[ "$BACKUP_DIR" =~ [[:space:]] || "$BACKUP_DIR" =~ [^a-zA-Z0-9_./-] || "$BACKUP_DIR" =~ \.\. || "$BACKUP_DIR" =~ // ]]; then
    echo "错误：备份目录格式不正确！"
    exit 1
fi

mkdir -p "$BACKUP_DIR"
BACKUP_DIR=$(readlink -f "$BACKUP_DIR")

PG_POD=$(kubectl get pod -n pg-system -l 'cnpg.io/instanceRole=primary' -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)

if [ -z "$PG_POD" ]; then
    echo "错误：未找到PostgreSQL Pod"
    exit 1
fi

DB_EXISTS=$(kubectl exec -n pg-system $PG_POD -c postgres -- psql -tAc "SELECT 1 FROM pg_database WHERE datname = '$DBNAME'" | tr -d '[:space:]')
if [ "$DB_EXISTS" != "1" ]; then
    DB_LIST=$(kubectl exec -n pg-system $PG_POD -c postgres -- psql -tAc "SELECT datname FROM pg_database WHERE datname NOT LIKE 'template%' AND datname NOT IN ('postgres','example') ORDER BY datname" | tr '\n' ' ')
    echo "错误：数据库 '$DBNAME' 不存在，已知数据库列表: $DB_LIST"
    exit 1
fi

# 生成备份文件名
TS=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${DBNAME}_${TS}.backup"
CONTAINER_FILE="var/lib/postgresql/data/${BACKUP_FILE}"

# 注册清理函数，在脚本退出时执行
trap "kubectl exec -n pg-system $PG_POD -c postgres -- rm -f $CONTAINER_FILE" INT TERM EXIT

# 执行备份操作
now=$(date +%S)
echo "开始备份数据库，请耐心等待..."
kubectl exec -n pg-system  $PG_POD -c postgres -- pg_dump -Fc --no-owner -d $DBNAME -f $CONTAINER_FILE || {
    echo "错误: 备份数据库 '$DBNAME' 失败！"
    exit 1
}

# 复制备份文件到本地
kubectl cp -n pg-system -c postgres $PG_POD:$CONTAINER_FILE "$BACKUP_DIR/$BACKUP_FILE" || {
    echo "错误: 备份文件复制到本地失败！"
    exit 1
}

duration=$(($(date +%S) - $now))
echo "备份成功完成！耗时 $((duration / 60)) 分 $((duration % 60)) 秒"
echo "备份文件路径: $BACKUP_DIR/$BACKUP_FILE"